#define MSETHTOOL_C
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#if defined(OS_LINUX_SOC)
#include <sys/types.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <net/if.h> 

#include <linux/ethtool.h> 
#include <linux/sockios.h> 
#endif
//set start flag
#include <libmscommon/mscommon.h>
#include <libmslog/mslog.h>

#define FLAG "ETHTOOL"
void msethtool_api_checkPort(char *ethname,char second)
{
	char cmdbuf[256]={0};
	if(0==second){
		second=3;
	}
	sprintf(cmdbuf,"ethtool -p %s %d",ethname,second);
	ms_cmdRet(cmdbuf);
}

ms_s08 msethtool_api_getInfo(ms_cstring ms_in devname, 
	ms_pu32 ms_out speed, ms_pu08 ms_out  duplex, ms_pu08 ms_out  autoneg, ms_bool* ms_out  link) 
{ 
	ms_bufcheckRetDes(-1, devname,"param## devname");
	ms_bufcheckRetDes(-1, speed,"param## speed");
	ms_bufcheckRetDes(-1, duplex,"param## duplex");
	ms_bufcheckRetDes(-1, autoneg,"param## autoneg");
	ms_bufcheckRetDes(-1, link,"param## link");
#if defined(OS_LINUX_SOC)
	int fd  = socket(AF_INET, SOCK_DGRAM, 0); 
	if (fd < 0) { 
		ms_errRet(-1,"ethtool_gset Cannot get control socket"); 
	} 
	
	struct ifreq ifr; 
	struct ethtool_cmd ecmd; 
	memset(&ifr, 0, sizeof(ifr)); 
	ms_strcpy(ifr.ifr_name, devname); 
	ecmd.cmd = ETHTOOL_GSET; 
	ifr.ifr_data = (caddr_t)&ecmd; 
	int err = ioctl(fd, SIOCETHTOOL, &ifr); 
	if (!(err < 0)) { 
		//ms_debug("[%s]PHY xx - %d/%s ",devname, ecmd.speed, (ecmd.duplex == DUPLEX_FULL) ? "Full" : "Half"); 
		//ms_debug("[%s]Auto-negotiation: %s ",devname, (ecmd.autoneg == AUTONEG_DISABLE) ? "off" : "on"); 
		switch (ecmd.speed) { 
			case SPEED_10: 
			case SPEED_100: 
			case SPEED_1000: 
			case SPEED_2500: 
			case SPEED_10000: 
				*speed = ecmd.speed; 
				break; 
			default: 
				//ms_debug("Unknown! (%i)\n", ecmd.speed); 
				*speed =-1;
				break; 
		}; 

		switch (ecmd.duplex) { 
			case DUPLEX_HALF: 
			case DUPLEX_FULL: 
				*duplex = ecmd.duplex; 
				break; 
			default: 
				//ms_debug("Unknown! (%i)\n", ecmd.duplex); 
				*duplex=-1;
				break; 
		}; 
		
		*autoneg = ecmd.autoneg; 
	} 
	struct ethtool_value edata; 
	edata.cmd = ETHTOOL_GLINK; 
	ifr.ifr_data = (caddr_t)&edata; 
	err = ioctl(fd, SIOCETHTOOL, &ifr); 
	if (err == 0) { 
		*link = edata.data ? ms_true: ms_false; 
		//ms_debug("[%s]%s",devname, edata.data ? "Up" : "Down"); 
	} else if (errno != EOPNOTSUPP) { 
		ms_error("Cannot get link status"); 
	} 
	close(fd); 
#else
#endif
	return 0; 
} 

int msethtool_api_setInfo(const char* devname, int speed, int duplex, int autoneg) 
{ 
	ms_bufcheckRetDes(-1, devname,"param## devname");
#if defined(OS_LINUX_SOC)
	ms_bufcheckRetDes(-1, devname, "Please input vaild devname");

	int fd = socket(AF_INET, SOCK_DGRAM, 0); 
	if (fd < 0) { 
		ms_errRet(-1,"ethtool_sset Cannot get control socket"); 
	} 
	
	struct ethtool_cmd ecmd; 
	struct ifreq ifr; 
	ms_strcpy(ifr.ifr_name, devname); 
	ecmd.cmd = ETHTOOL_GSET; 
	ifr.ifr_data = (caddr_t)&ecmd; 
	int err = ioctl(fd, SIOCETHTOOL, &ifr); 
	if (err < 0) { 
		ms_errRet(-1,"ETHTOOL_GSET failed"); 
	} 

	if (speed != -1){
		ecmd.speed = speed;
	}
	if (duplex != -1) {
		ecmd.duplex = duplex; 
	}
	if (autoneg != -1) {
		ecmd.autoneg = autoneg; 
	}
	
	int advertising = -1; 
	if ((autoneg == AUTONEG_ENABLE) && (advertising < 0)) { 
		if (speed == SPEED_10 && duplex == DUPLEX_HALF) {
			advertising = ADVERTISED_10baseT_Half; 
		}else if (speed == SPEED_10 && duplex == DUPLEX_FULL) {
			advertising = ADVERTISED_10baseT_Full; 
		}else if (speed == SPEED_100 && duplex == DUPLEX_HALF) {
			advertising = ADVERTISED_100baseT_Half; 
		}else if (speed == SPEED_100 && duplex == DUPLEX_FULL) {
			advertising = ADVERTISED_100baseT_Full; 
		}else if (speed == SPEED_1000 && duplex == DUPLEX_HALF) {
			advertising = ADVERTISED_1000baseT_Half; 
		}else if (speed == SPEED_1000 && duplex == DUPLEX_FULL) {
			advertising = ADVERTISED_1000baseT_Full; 
		}else if (speed == SPEED_2500 && duplex == DUPLEX_FULL) {
			advertising = ADVERTISED_2500baseX_Full; 
		}else if (speed == SPEED_10000 && duplex == DUPLEX_FULL) {
			advertising = ADVERTISED_10000baseT_Full; 
		}else {
			advertising = ecmd.supported & (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | ADVERTISED_2500baseX_Full | ADVERTISED_10000baseT_Full); 
		}
	} 

	if (advertising != -1) { 
		ecmd.advertising = advertising; 
	} 

	ecmd.cmd = ETHTOOL_SSET; 
	ifr.ifr_data = (caddr_t)&ecmd; 
	err = ioctl(fd, SIOCETHTOOL, &ifr); 
	if (err < 0) { 
		ms_errRet(-1,"ETHTOOL_SSET failed"); 
	}
	close(fd); 
#else
#endif
	return 0; 
} 
#undef MSETHTOOL_C
